package com.ruoyi.coin.utils.web3j;

import com.ruoyi.coin.enums.OklinkChainEnum;
import com.ruoyi.common.config.CoinConfig;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.blade.Func;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.Response;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.http.HttpService;

import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.net.Proxy;

/**
 * 币安链
 */
@Slf4j
public class Web3jUtils {

    private static Web3j web3j_bsc = null;
    private static Web3j web3j_eth = null;
    private static Web3j web3j_base = null;

    static {
        OkHttpClient client = new OkHttpClient.Builder()
                .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(CoinConfig.getProxy_ip(), CoinConfig.getProxy_port())))
                .build();

        web3j_bsc = Web3j.build(new HttpService(CoinConfig.getRpc_bsc(), client));
        web3j_eth = Web3j.build(new HttpService(CoinConfig.getRpc_eth(), client));
        web3j_base = Web3j.build(new HttpService(CoinConfig.getRpc_base(), client));
    }

    public static void main(String[] args) {
        getWeb3j(OklinkChainEnum.BASE);
    }

    //获取web3j
    private static Web3j getWeb3j(OklinkChainEnum chainEnum) {
        Web3j web3j = null;
        try {
            if (Func.equals(OklinkChainEnum.BSC, chainEnum)) {
                web3j = web3j_bsc;
            } else if (Func.equals(OklinkChainEnum.ETH, chainEnum)) {
                web3j = web3j_eth;
            }else if (Func.equals(OklinkChainEnum.BASE, chainEnum)) {
                web3j = web3j_base;
            }

            BigInteger blockNumber = web3j.ethBlockNumber().send().getBlockNumber();
            System.out.println(chainEnum.getName()+" blockNumber="+blockNumber);
            if (blockNumber.compareTo(BigInteger.ZERO) == 1) {//有在线
                return web3j;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        OkHttpClient client = new OkHttpClient.Builder()
                .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(CoinConfig.getProxy_ip(), CoinConfig.getProxy_port())))
                .build();

        if (Func.equals(OklinkChainEnum.BSC, chainEnum)) {
            web3j_bsc = Web3j.build(new HttpService(CoinConfig.getRpc_bsc(), client));
            web3j = web3j_bsc;
        } else if (Func.equals(OklinkChainEnum.ETH, chainEnum)) {
            web3j_eth = Web3j.build(new HttpService(CoinConfig.getRpc_eth(), client));
            web3j = web3j_eth;
        }else if (Func.equals(OklinkChainEnum.BASE, chainEnum)) {
            web3j_base = Web3j.build(new HttpService(CoinConfig.getRpc_base(), client));
            web3j = web3j_base;
        }

        return web3j;
    }


    //获取账号交易次数Nonce
    public static BigInteger getNonce(OklinkChainEnum chainEnum, String walletAddress) {
        try {
            Web3j bscWeb3j=getWeb3j(chainEnum);

            EthGetTransactionCount getNonce = bscWeb3j.ethGetTransactionCount(walletAddress, DefaultBlockParameterName.LATEST).send();
            if (getNonce == null) {
                throw new RuntimeException("nonce 为空");
            }
            //链上
            BigInteger onlineNonce = getNonce.getTransactionCount();

            return onlineNonce;
        } catch (Exception e) {
            throw new RuntimeException("获取账户的Nonce 异常");
        }
    }


    //链上交易
    public static String transOnline(OklinkChainEnum chainEnum, String sign) {
        try {
            Web3j web3j = getWeb3j(chainEnum);

            // 发送裸交易请求
            EthSendTransaction bnbSendTransaction = web3j.ethSendRawTransaction(sign).sendAsync().get();
            Response.Error error = bnbSendTransaction.getError();
            if (Func.isNotEmpty(error)) {
                String message = error.getMessage();
                log.info("链上转账有误-----》" + message);
                throw new ServiceException(message);
            }
            String hash = bnbSendTransaction.getTransactionHash();
            System.out.println("链上转账哈希-----》" + hash);
            return hash;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
    }

}
